package greetings

import (
	"context"
	"fmt"
	"log"
	"time"

	redis "github.com/go-redis/redis/v8"
	"github.com/spf13/viper"
)

//这个是全局的对象
//程序结束的时候，需要关闭网络资源。
var REDIS_CONN *redis.Client
var REDIS_CONTEXT = context.Background()

func init() {

	viper.SetConfigName("config")
	viper.SetConfigFile("../resource/app.yaml")

	viper.WatchConfig()

	redis_ip := viper.GetString("redis.ip")
	redis_password := viper.GetString("redis.password")

	log.Println("init redis config ................... IP:", redis_ip)

	//init
	REDIS_CONN = redis.NewClient(&redis.Options{
		Addr:     redis_ip,
		Password: redis_password,
		DB:       0,
	})

	_, err := REDIS_CONN.Ping(REDIS_CONTEXT).Result()

	if err != nil {
		panic(err)
	}

	log.Println("init redis config success ................... IP:", redis_ip)
}

func RedisDemo() {

	defer REDIS_CONN.Close()
	const redis_demo_key = "go:redis:demo"
	const redis_demo_val = "123456787"
	redisSet(redis_demo_key, redis_demo_val)
	val := redisGet(redis_demo_key)
	fmt.Println("go:redis:demo", val)

	val2, err := REDIS_CONN.Get(REDIS_CONTEXT, "key2").Result()
	if err == redis.Nil {
		fmt.Println("key2 does not exist")
	} else if err != nil {
		panic(err)
	} else {
		fmt.Println("key2", val2)
	}

	REDIS_CONN.SetNX(REDIS_CONTEXT, redis_demo_key, redis_demo_val, 1*time.Second).Result()
	time.Sleep(2 * time.Second)
	fmt.Println("key not existed any more", redis_demo_key)

	REDIS_CONN.SetNX(REDIS_CONTEXT, "key", "value", redis.KeepTTL).Result()
	REDIS_CONN.Sort(REDIS_CONTEXT, "list", &redis.Sort{Offset: 0, Count: 2, Order: "ASC"}).Result()
	vals1, err := REDIS_CONN.ZRangeByScoreWithScores(REDIS_CONTEXT, "zset", &redis.ZRangeBy{
		Min:    "-inf",
		Max:    "+inf",
		Offset: 0,
		Count:  2,
	}).Result()

	fmt.Println("vals1 ", vals1)

	// ZINTERSTORE out 2 zset1 zset2 WEIGHTS 2 3 AGGREGATE SUM
	vals2, err := REDIS_CONN.ZInterStore(REDIS_CONTEXT, "out", &redis.ZStore{
		Keys:      []string{"zset1", "zset2"},
		Weights:   []float64{2, 3},
		Aggregate: "MAX",
	}).Result()
	fmt.Println("vals2 ", vals2)

	// EVAL "return {KEYS[1],ARGV[1]}" 1 "key" "hello"
	vals3, err := REDIS_CONN.Eval(REDIS_CONTEXT, "return {KEYS[1],ARGV[1]}", []string{"key"}, "hello").Result()
	fmt.Println("vals3 ", vals3)
	// custom command
	res4, err := REDIS_CONN.Do(REDIS_CONTEXT, "set", "key", "value").Result()
	fmt.Println("vals4 ", res4)
}

func redisGet(k string) string {

	val, err := REDIS_CONN.Get(REDIS_CONTEXT, k).Result()
	if err != nil {
		panic(err)
	}
	return val
}

func redisSet(k string, v string) {

	if v == "" || k == "" {
		log.Println("redis set error key or value is empty :", k, v)
		return
	}
	err := REDIS_CONN.Set(REDIS_CONTEXT, k, v, 0).Err()
	if err != nil {
		panic(err)
	}
}
